package com.shmilyou.dissertationmanagement.web;
/* Created with 岂止是一丝涟漪     530060499@qq.com    2019年2月9日 22:15:27 */

import com.shmilyou.dissertationmanagement.biz.ThesisPublishTypeService;
import com.shmilyou.dissertationmanagement.biz.ThesisService;
import com.shmilyou.dissertationmanagement.biz.ThesisTypeService;
import com.shmilyou.dissertationmanagement.domain.Thesis;
import com.shmilyou.dissertationmanagement.domain.ThesisEx;
import com.shmilyou.dissertationmanagement.domain.ThesisPublishType;
import com.shmilyou.dissertationmanagement.domain.ThesisType;
import com.shmilyou.dissertationmanagement.tools.Utils;
import com.shmilyou.dissertationmanagement.utils.Constant;
import com.shmilyou.dissertationmanagement.utils.WebUtils;
import com.shmilyou.dissertationmanagement.web.vo.ThesisVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


@Controller
public class ThesisController {
    private final static Logger log = LoggerFactory.getLogger(ThesisController.class);

    private final ThesisService thesisService;
    private final ThesisTypeService thesisTypeService;
    private final ThesisPublishTypeService thesisPublishTypeService;

    @Autowired
    public ThesisController(ThesisService thesisService,
                            ThesisTypeService thesisTypeService,
                            ThesisPublishTypeService thesisPublishTypeService) {

        this.thesisService = thesisService;
        this.thesisTypeService = thesisTypeService;
        this.thesisPublishTypeService = thesisPublishTypeService;
    }

    @RequestMapping("/thesis")
    public String index(Integer pageIndex, Map<Object, Object> map) {
        if (pageIndex == null) {
            pageIndex = 1;
        }

        Object lock1 = new Object();
        Object lock2 = new Object();
        AtomicBoolean flag1 = new AtomicBoolean(true);
        AtomicBoolean flag2 = new AtomicBoolean(true);

        //get all data
        Integer finalPageIndex = pageIndex;
        AtomicReference<Page<Thesis>> page = new AtomicReference<>();
        AtomicReference<List<ThesisEx>> thesisExes = new AtomicReference<>();
        new Thread(() -> {
            page.set(thesisService.queryAll(finalPageIndex - 1, 5));
            thesisExes.set(thesisService.queryExById(page.get().getContent().stream().map(Thesis::getId).collect(Collectors.toList())));
            synchronized (lock1) {
                flag1.set(false);
                lock1.notifyAll();
            }
        }, "loadAllTheses").start();

        AtomicReference<List<ThesisType>> thesisTypes = new AtomicReference<>();
        AtomicReference<List<ThesisPublishType>> thesisPublishTypes = new AtomicReference<>();
        new Thread(() -> {
            thesisTypes.set(thesisTypeService.queryAll());
            thesisPublishTypes.set(thesisPublishTypeService.queryAll());
            synchronized (lock2) {
                flag2.set(false);
                lock2.notifyAll();
            }
        }, "loadAllTypes").start();

        synchronized (lock1) {
            while (flag1.get()) {
                try {
                    lock1.wait();
                } catch (InterruptedException e) {
                    log.error(e.getLocalizedMessage(), e.getMessage());
                }
            }
        }

        synchronized (lock2) {
            while (flag2.get()) {
                try {
                    lock2.wait();
                } catch (InterruptedException e) {
                    log.error(e.getLocalizedMessage(), e.getMessage());
                }
            }
        }

        // join data
        List<ThesisVO> entities = new ArrayList<>(page.get().getNumber());
        ThesisVO thesisVO;
        ThesisEx thesisEx;
        ThesisType thesisType;
        ThesisPublishType thesisPublishType;
        for (Thesis i : page.get().getContent()) {
            thesisEx = thesisExes.get().stream().filter(a -> a.getId().equals(i.getId())).findFirst().orElse(new ThesisEx());
            thesisType =
                    thesisTypes.get().stream().filter(b -> b.getId().equals(i.getThesisTypeId())).findFirst().orElse(new ThesisType());
            thesisPublishType =
                    thesisPublishTypes.get().stream().filter(c -> c.getId().equals(i.getThesisPublishTypeId())).findFirst().orElse(new ThesisPublishType());
            thesisVO = new ThesisVO();
            BeanUtils.copyProperties(i, thesisVO);
            thesisVO.setThesisTypeName(thesisType.getName());
            thesisVO.setThesisTypeNumber(thesisType.getNumber());
            thesisVO.setThesisPublishTypeName(thesisPublishType.getName());
            thesisVO.setThesisPublishTypeContent(thesisEx.getPublishTypeContent());
            thesisVO.setThesisTypeId(thesisType.getId());
            thesisVO.setThesisPublishTypeId(thesisPublishType.getId());
            entities.add(thesisVO);
        }

        map.put("theses", entities);
        map.put("page", page);
        return "thesis";
    }

    @RequestMapping(value = "/search/thesis", method = RequestMethod.GET)
    public String search(String name, ModelMap map) {
        if (StringUtils.isEmpty(name)) {
            return "redirect:/thesis";
        }
        List<Thesis> theses = thesisService.queryByName(name);
        map.put("theses", theses);
        return "thesis";
    }

    @RequestMapping(value = "/thesis/rm", method = RequestMethod.POST)
    public ResponseEntity<Map<String, Object>> delete(String id) {
        if (Utils.isInteger(id)) {
            Thesis exit = thesisService.queryById(Integer.parseInt(id));
            if (exit != null) {
                thesisService.delete(exit);
                return WebUtils.success();
            }
        }
        return WebUtils.failure();
    }

    @RequestMapping(value = "/thesis/edit", method = RequestMethod.GET)
    public String edit(String id, Map<String, Object> map) {
        if (Utils.isInteger(id)) {
            Thesis thesis = thesisService.queryById(Integer.parseInt(id));
            ThesisEx thesisEx = thesisService.queryExById(thesis.getId());
            ThesisVO entity = new ThesisVO();
            BeanUtils.copyProperties(thesis, entity);
            entity.setThesisTypeNumber(thesisEx.getTypeNumber());
            entity.setThesisPublishTypeContent(thesisEx.getPublishTypeContent());
            List<ThesisType> thesisTypes = thesisTypeService.queryAll();
            List<ThesisPublishType> thesisPublishTypes = thesisPublishTypeService.queryAll();

            map.put("entity", entity);
            map.put("thesisTypes", thesisTypes);
            map.put("thesisPublishTypes", thesisPublishTypes);
            return "thesis_edit";
        }
        return "error";
    }

    @RequestMapping(value = "/thesis/add", method = RequestMethod.GET)
    public String add(Map<String, Object> map) {
        List<ThesisType> thesisTypes = thesisTypeService.queryAll();
        List<ThesisPublishType> thesisPublishTypes = thesisPublishTypeService.queryAll();


        map.put("thesisTypes", thesisTypes);
        map.put("thesisPublishTypes", thesisPublishTypes);
        return "thesis_add";
    }

    @RequestMapping(value = "/thesis/edit", method = RequestMethod.POST)
    public ResponseEntity<Map<String, Object>> editHandle(ThesisVO thesisVO, @RequestParam MultipartFile file) {
        if (file.getSize() > 0) {
            String attachment = WebUtils.saveUploadFile(file, Constant.THESIS_ATTACHMENTS_PATH);
            thesisVO.setAttachment(attachment);
        }
        Thesis entity = new Thesis();
        BeanUtils.copyProperties(thesisVO, entity);
        thesisService.update(entity);
        //handle type and publish-type
        ThesisEx thesisEx = new ThesisEx(entity.getId(), thesisVO.getThesisTypeName(), thesisVO.getThesisPublishTypeContent());
        thesisService.saveThesisEx(thesisEx);
        return WebUtils.success();
    }

    @RequestMapping(value = "/thesis/add", method = RequestMethod.POST)
    public ResponseEntity<Map<String, Object>> addHandle(ThesisVO thesisVO, @RequestParam MultipartFile file) {
        String attachment = WebUtils.saveUploadFile(file, Constant.THESIS_ATTACHMENTS_PATH);
        if (!StringUtils.isEmpty(attachment)) {
            thesisVO.setAttachment(attachment);
        }
        Thesis entity = new Thesis();
        BeanUtils.copyProperties(thesisVO, entity);
        thesisService.save(entity);
        //handle type and publish-type
        ThesisEx thesisEx = new ThesisEx(entity.getId(), thesisVO.getThesisTypeName(), thesisVO.getThesisPublishTypeContent());
        thesisService.saveThesisEx(thesisEx);
        return WebUtils.success();
    }

    @RequestMapping(value = "/thesis/export", method = RequestMethod.POST)
    public ResponseEntity<Map<String, Object>> exportThesis() {
        //get all data
        List<Thesis> page = thesisService.queryAll();
        List<ThesisEx> thesisExes = thesisService.queryExById(page.stream().map(Thesis::getId).collect(Collectors.toList()));
        List<ThesisType> thesisTypes = thesisTypeService.queryAll();
        List<ThesisPublishType> thesisPublishTypes = thesisPublishTypeService.queryAll();

        // join data
        List<ThesisVO> entities = new ArrayList<>(page.size());
        ThesisVO thesisVO;
        ThesisEx thesisEx;
        ThesisType thesisType;
        ThesisPublishType thesisPublishType;
        for (Thesis i : page) {
            thesisEx = thesisExes.stream().filter(a -> a.getId().equals(i.getId())).findFirst().orElse(new ThesisEx());
            thesisType =
                    thesisTypes.stream().filter(b -> b.getId().equals(i.getThesisTypeId())).findFirst().orElse(new ThesisType());
            thesisPublishType =
                    thesisPublishTypes.stream().filter(c -> c.getId().equals(i.getThesisPublishTypeId())).findFirst().orElse(new ThesisPublishType());
            thesisVO = new ThesisVO();
            BeanUtils.copyProperties(i, thesisVO);
            thesisVO.setThesisTypeName(thesisType.getName());
            thesisVO.setThesisTypeNumber(thesisType.getNumber());
            thesisVO.setThesisPublishTypeName(thesisPublishType.getName());
            thesisVO.setThesisPublishTypeContent(thesisEx.getPublishTypeContent());
            thesisVO.setThesisTypeId(thesisType.getId());
            thesisVO.setThesisPublishTypeId(thesisPublishType.getId());
            entities.add(thesisVO);
        }
        return WebUtils.success(entities);
    }
}
